<template>
  <div class="popover-radio-tree-box">
    <q-input v-if="filter"
             color="grey-5"
             placeholder="搜索"
             v-model="filterText"
             class="mg-tree-search-input q-mb-xs"
             clearable />
    <q-tree :nodes="data"
            :ref="refId"
            color="light"
            control-color="secondary"
            text-color="dark"
            accordion
            :expanded.sync="expandedList"
            :filter="filterText"
            no-nodes-label="暂无数据"
            no-results-label="未找到匹配数据"
            :node-key="nodeKey"
            class="mg-tree mg-tree-single">
      <div :slot="`default-header`"
           slot-scope="prop"
           class="row items-center cursor-pointer"
           :class="{'leaf-active': selectNode === prop.node[nodeKey]}"
           @click="nodeClick(prop)">
        <div>{{ prop.node[nodeLabel] }}</div>
      </div>
    </q-tree>
  </div>
</template>

<script>
import { QTree, QInput, uid } from 'quasar'
import { getLeafByKey, getFirstCheckedLeafNode, getParentCodes } from './util'
export default {
  name: 'MgTree',
  components: {
    QTree,
    QInput
  },
  props: {
    data: { // 支持多棵树
      type: Array,
      required: true
    },
    filter: { // 是否支持过滤
      type: Boolean,
      default: true
    },
    nodeKey: { // 节点唯一标识名
      type: String,
      default: 'code'
    },
    nodeLabel: { // 数据中的显示字段名
      type: String,
      default: 'label'
    },
    initTicked: { // 初始勾选项 [code]
      type: Array,
      default: () => []
    },
    tickChange: { // 将勾选项通知父组件 参数为当前选中项
      type: Function,
      required: false
    }
  },
  data () {
    return {
      refId: uid(),
      selectNode: null,
      filterText: '', // 过滤关键字
      expandedList: [] // 默认展开的节点
    }
  },
  created () {
    this.init()
  },
  beforeDestroy () {
    // 有选中项，则将选中项通知父组件
    this.selectNode && typeof this.tickChange === 'function' && this.tickChange([this.selectNode])
  },
  watch: {
    filterText (value) { // 输入搜索内容,则展开所有节点; 否则,只展开第一层
      if (value) {
        this.$children[1].expandAll()
      } else { // 清除搜索，则展开到选中节点
        this.expandedList = getParentCodes(this.data, this.selectNode || '', this.nodeKey)
      }
    }
  },
  methods: {
    init () {
      if (this.initTicked && this.initTicked[0]) {
        const node = getLeafByKey(this.initTicked[0], this.nodeKey, this.data)
        // 若有选中的叶子节点，则展开到该叶子节点
        if (node) {
          node['checked'] = true
          this.selectNode = node[this.nodeKey]
          // 展开所有父节点
          this.expandedList = getParentCodes(this.data, this.selectNode || '', this.nodeKey)
        }
      } else { // 无选中的节点，则展开第一层
        this.expandedList = this.data.map(item => item[this.nodeKey])
      }
    },
    nodeClick ({ node }) {
      const children = node.children || []
      if (children.length || node[this.nodeKey] === this.selectNode) {
        return
      }
      // 更新选中项：先重置上次选中节点的状态，再设置新节点的选中状态
      const originNode = getFirstCheckedLeafNode(this.selectNode)
      originNode && (originNode['checked'] = false)
      node['checked'] = true
      this.selectNode = node[this.nodeKey]
    }
  }
}
</script>

<style lang="stylus" scoped>
.popover-radio-tree-box
  padding 10px 15px
  .leaf-active
    background-color rgba(0, 0, 0, .1)
    padding 4px
    border-radius 2px
</style>
<style lang="stylus">
.popover-radio-tree-box
  .q-tree-node-header span.row.no-wrap.items-center.text-black
    display inline-block
    width 100%
</style>
